# -*- coding: UTF-8 -*-
import datetime
import json
from typing import List

from common_libs import datetime_utils
from common_libs.enum_model import ReturnFlag
from dispatcher.common_utils.constants import ALLOW_DISPATCH_TASK_TYPES


class BlockBean(object):

    def __init__(self, data_block):
        # 数据信息
        self.server = data_block.get('server')  # 调用方系统名称
        self.block_sn = data_block.get('block_sn')  # 数据块唯一编号
        self.data_block = data_block.get('data_block')  # 数据块，一般为json格式

        # 任务信息
        # self.task_id = data_block.get('task_id')  # 调度任务ID
        self.id = data_block.get('id')  # 调度任务ID # todo 持久化到数据库中就是主键ID
        self.task_type = data_block.get('task_type')  # 任务类型，不同的任务类型会有不同的处理方式
        self.dispatch_type = data_block.get('dispatch_type')  # 调度类型，即时任务，和延时任务
        self.state = data_block.get('state')  # 任务状态，00：待抓取 01：已抓取 02：已消费 03：处理中 04：成功 05：失败 06：超时
        self.task_log = data_block.get('task_log')  # 任务执行日志
        self.remain_try_times = data_block.get('remain_try_times')  # 任务剩余尝试次数
        self.max_try_times = data_block.get('max_try_times')  # 任务最大尝试次数
        self.retry_time_interval = data_block.get('retry_time_interval')  # 时间间隔,单位为秒，格式[int number,...],比如[1, 2]代表第一次时间间隔为1秒，后续的间隔为2秒；[1]全部间隔为1秒

        # 时间信息
        self.next_try_time = data_block.get('next_try_time') or datetime.datetime.now()  # 任务下次尝试处理时间
        self.last_try_time = data_block.get('last_try_time')  # 任务最后一次执行时间，过期后不再重试 # todo 或许可以用来停止任务
        self.delay_second = data_block.get('delay_second')  # 任务剩余延时时间，60秒以内的短期延时  # 留着这个字段是为了业务使用方便

        # 额外信息
        self.remark = data_block.get('remark', '')   # 备注(longtext)
        self.extend = data_block.get('extend', '')   # 扩展字段(64位,有索引)

    def to_dict(self, exclude: List = None):
        exclude = exclude if exclude else []

        return {k: v for k, v in self.__dict__.items() if k not in exclude}

    def init_check_bean(self):
        # todo 这里应该包含所有的参数校验，这里成功那么就可进行调度
        # 调度任务基本格式检查
        if not (self.block_sn and self.block_sn and self.server and self.dispatch_type):
            return None, ReturnFlag(msg="调度任务基本格式检查失败: 任务必要字段缺失", flag=False)
        if self.remain_try_times <= 0:
            return None, ReturnFlag(msg="调度任务基本格式检查失败: 任务已达最大重试次数", flag=False)

        # 调度任务内容可行性检查
        data_block = self.data_block if isinstance(self.data_block, str) else json.loads(self.data_block)
        if not data_block.get('url'):
            return None, ReturnFlag(msg="调度任务内容可行性检查失败: 任务必要字段缺失", flag=False)
        if self.is_timeout():
            return None, ReturnFlag(msg="调度任务内容可行性检查失败: 任务已过期", flag=False)
        if self.dispatch_type not in ALLOW_DISPATCH_TASK_TYPES:
            return None, ReturnFlag(msg="调度任务内容可行性检查失败: 不允许调度的任务类型", flag=False)

        self.remark = self.to_dict(exclude=["remark", "extend"])   # 备份原始数据，任务在执行过程中可能会被修改，像是delay_second
        return self, ReturnFlag(msg="任务可调度", flag=True)

    def is_timeout(self):
        if isinstance(self.last_try_time, str):
            return datetime_utils.get_time(source=self.last_try_time) <= datetime.datetime.now()
        return self.last_try_time <= datetime.datetime.now()

    def refresh_next_try_time(self):
        self.next_try_time += datetime.timedelta(seconds=self.delay_second)
        return self

